package csm.sql;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.commons.configuration.Configuration;

import csm.common.configuration.ConfigHandler;
import csm.sql.parameters.ParameterBase;

/**
 * 
 * @author seungmun
 * @since 2006.1.18.
 * @version
 * @see
 */
public final class DBConfig
{
	private String connectionName = "default";
	private ConnectionFactory cp;
	private String dbms;
	private ParameterBase parameter;
	private HashMap<String, String> settings;

	protected DBConfig()
	{
		
	}
	
	public void init(HashMap<String, String> settings)
	{
		this.settings = settings;
		this.connectionName = this.settings.get("connection[@name]");
		this.dbms = this.settings.get("connection.dbms");
		
		String parameterClassName = String.format("csm.sql.parameters.%1$sParameter", dbms);
		try
		{
			this.parameter = (ParameterBase) Class.forName(parameterClassName).newInstance();
		}
		catch (ClassNotFoundException e)
		{
			System.err.println(parameterClassName);
			e.printStackTrace();
		}
		catch (InstantiationException e)
		{
			System.err.println(parameterClassName);
			e.printStackTrace();
		}
		catch (IllegalAccessException e)
		{
			System.err.println(parameterClassName);
			e.printStackTrace();
		}
	}
	
	public String getConnectionName(){
		return this.connectionName;
	}

	public String getSettings(String key)
	{
		return this.settings.get(key);
	}

	public ConnectionFactory getConnectionFactory()
	{
		try
		{
			if (this.cp == null) this.cp = ConnectionFactory.newInstance(this.connectionName);
		}
		catch (SQLException e)
		{
			e.printStackTrace();
		}

		return this.cp;
	}

	public static DBConfig getDBConfig()
	{
		return dbConfigList.get("default");
	}

	public static DBConfig getDBConfig(String connectionName)
	{
		return dbConfigList.get(connectionName);
	}

	private static HashMap<String, DBConfig> dbConfigList;

	static
	{
		DBConfig dbc = null;
		dbConfigList = new HashMap<String, DBConfig>();

		ConfigHandler cf = null;
		Configuration c = null;
		cf = ConfigHandler.getInstance("config.xml");
		
		if( cf != null )
			c = cf.getConfiguration();
		
		if (c != null)
		{
			Object prop = c.getProperty("connection.dbms");
			if (prop != null && prop instanceof Collection)
			{
				HashMap<String, String> configItem = null;

				int connectionSettingCount = ((Collection<?>) prop).size();

				String connectionPrefix = "";
				String connectionName = "";
				for (int i = 0; i < connectionSettingCount; i++)
				{
					connectionPrefix = String.format("connection(%s)", i);
					connectionName = c.getString(connectionPrefix + "[@name]");
					configItem = new HashMap<String, String>();
					
					@SuppressWarnings("unchecked")
					Iterator<String> is = c.getKeys(connectionPrefix);
					
					while (is.hasNext())
					{
						String elementName = is.next();
						configItem.put(elementName.replace(connectionPrefix, "connection"), c.getString(elementName));
					}

					dbc = new DBConfig();
					dbc.init(configItem);
					dbConfigList.put(connectionName, dbc);
				}
			}
		}
	}

	/**
	 * DBMS
	 * 
	 * @return
	 */
	public String getDbms()
	{
		return dbms;
	}

	public Connection getConnection() throws SQLException
	{
		try
		{
			if (this.cp == null) this.cp = ConnectionFactory.newInstance(this.connectionName);

			return cp.getConnection();
		}
		catch (Exception e)
		{
			for (int i = 1; i < 3; i++)
			{
				try
				{
					return cp.getConnection();
				}
				catch (Exception e1)
				{
					try
					{
						Thread.sleep(100);
					}
					catch (InterruptedException e2)
					{
					}
				}
			}
			throw new SQLException("DB연결에 실패했습니다.", e);
		}
	}

	public ParameterBase getParameter()
	{
		return parameter;
	}

	public void setParameter(ParameterBase parameter)
	{
		this.parameter = parameter;
	}
}
